
#include <iostream>
#include <string>
#include <list>
using namespace std;

#include <boost/intrusive_ptr.hpp>
#include <boost/pool/pool_alloc.hpp>

#ifdef a
#define a
#if 1
#elif 3
#endif

#endif

#define NEW_WITH_ALLOCATOR(Class,Alloc) void *operator new(size_t) {	\
		cout << #Class"::new" << endl;				\
		Alloc _alloc;						\
		return _alloc.allocate();				\
	}								\
	void operator delete (void *p) {				\
		cout << #Class"::delete" << endl;			\
		Alloc _alloc;						\
		_alloc.deallocate(static_cast<Class *>(p));		\
	}								\
	void *operator new (size_t, Class *p) {				\
		cout << #Class"::new(p)" << endl;			\
		return p;						\
	}								\
	void operator delete (void *, Class *p) {			\
		cout << #Class"::delete(p)" << endl;			\
	}								\
	void *operator new[] (size_t p_size) {				\
		cout << #Class"::new[](" << p_size << ")" << endl;	\
		cout << "sizeof(" #Class "): " << sizeof(Class) << endl; \
		Alloc _alloc;						\
		return _alloc.allocate(p_size / sizeof(Class));		\
	}								\
	void operator delete[] (void *p, size_t p_size) {		\
		cout << #Class"::delete[](" << p_size << ")" << endl;	\
		Alloc _alloc;						\
		_alloc.deallocate(static_cast<Class *>(p), p_size / sizeof(Class)); \
	}								\
	void *operator new[] (size_t, Class *p) {			\
		cout << #Class"::new()[]" << endl;			\
		return p;						\
	}								\
	void operator delete[] (void *, Class *p) {			\
		cout << #Class"::delete()[]" << endl;			\
	}


class ref_count {
public:
	ref_count () : m_count(0) {}
	virtual ~ref_count() {}
	inline
	void add_ref () {
		++m_count;
	}
	inline
	bool release () {
		return 0 == (--m_count);
	}

private:
	int m_count;
};

inline
void intrusive_ptr_add_ref (ref_count *p_counter) {
	p_counter->add_ref();
}

inline
void intrusive_ptr_release (ref_count *p_counter) {
	if (p_counter->release())
		delete p_counter;
}

class kv_list : public ref_count {
public:
	typedef boost::fast_pool_allocator<kv_list> allocator;
	typedef boost::intrusive_ptr<kv_list> pointer;

	NEW_WITH_ALLOCATOR(kv_list, kv_list::allocator);
	
/*
	void *operator new (size_t) {
		cout << "allocate kv_list ptr" << endl;
		return allocator::allocate();
	}
	void *operator new (size_t, kv_list *p) {
		cout << "kv_list placement new" << endl;
		return p;
	}
	void operator delete (void *ptr) {
		cout << "deallocate kv_list ptr" << endl;
		allocator::deallocate(static_cast<kv_list*>(ptr));
	}
*/
public:
	kv_list () {
		cout << "kv_list()" << endl;
	}
	kv_list (const kv_list &rhs) {
		cout << "kv_list(const kv_list&)" << endl;
	}
	virtual ~kv_list () {
		cout << "~kv_list()" << endl;
	}

	virtual void * get_scanner () {
		return NULL;
	}
};

class table : public kv_list {
public:
	typedef boost::fast_pool_allocator<table> allocator;
	typedef boost::intrusive_ptr<table> pointer;

	NEW_WITH_ALLOCATOR(table, boost::fast_pool_allocator<table>);
/*
	// new & delete
	void *operator new (size_t) {
		cout << "allocate table ptr" << endl;
		return allocator::allocate();
	}
	void operator delete (void *ptr) {
		cout << "deallocate table ptr" << endl;
		allocator::deallocate(static_cast<table*>(ptr));
	}

	// placement new & delete
	void *operator new (size_t, table *p) {
		cout << "table placement new" << endl;
		return p;
	}
	// void operator delete (void *, table* p) {
	// 	cout << "table placement delete" << endl << flush;
	// }
*/
public:
	table () {
		cout << "table()" << endl << flush;
	}
	table (const table &rhs) {
		cout << "table(const table&)" << endl;
	}
	~table () {
		cout << "~table()" << endl;
	}
};

int main () try{
	const int count = 3;
	
	table *p = new table[count];
	union prefix_t {
		unsigned long _64;
		struct {
			unsigned char _0;
			unsigned char _1;
			unsigned char _2;
			unsigned char _3;
		} _8;
	};

	prefix_t *prefix((prefix_t*)(((unsigned char*)p) - 4));
	cout << hex
	     << prefix->_64 << endl
	     << prefix->_8._0 << " "
	     << prefix->_8._1 << " "
	     << prefix->_8._2 << " "
	     << prefix->_8._3 << endl;

	new(p) table;

	
	
	{
		list<table::pointer> tables;
		
		for (int i=0; i<count; ++i) {
			table::pointer ptr(new table);
			tables.push_back(ptr);
		}
	}
	{
		list<kv_list::pointer> lists;

		for (int i=0; i<count; ++i) {
			kv_list::pointer ptr;
			if (i%2)
				ptr = new kv_list;
			else
				ptr = new table;
			lists.push_back(ptr);
		}
	}
	{
		list<table, table::allocator> tables;
		table the_table;
		for (int i=0; i<count; ++i) {
			tables.push_back(the_table);
		}
	}

	return 0;
} catch (...) {
	return 0;
}

